package com.shuai.utils.tree;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * Tree工具类
 *
 * @author shuai
 * @since 2022
 */
@Slf4j
public class TreeUtil<T> {

    /**
     * 生成树形结构
     *
     * @param menuList
     * @param pid
     * @return
     */
    public static List<SysTreeVo> makeTreeForSysTree(List<SysTreeVo> menuList, String pid) {
        List<SysTreeVo> list = new ArrayList<>();
        Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                .filter(item -> item != null && item.getPid().equals(pid))
                .forEach(item -> {
                    SysTreeVo treeVo = new SysTreeVo();
                    BeanUtils.copyProperties(item, treeVo);
                    //获取每一个item的下级
                    List<SysTreeVo> children = makeTreeForSysTree(menuList, String.valueOf(item.getId()));
                    treeVo.setChildren(children);
                    list.add(treeVo);
                });
        return list;
    }

    /**
     * 生成树形结构
     *
     * @param menuList
     * @param pid
     * @param <T>
     * @return
     */
    public static <T> List<T> makeTreeForAny(List<T> menuList, String pid) {
        List<T> list = new ArrayList<>();
        Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                .filter(item -> {
                    try {
                        Field field = item.getClass().getDeclaredField("pid");
                        field.setAccessible(true);
                        String str = (String) field.get(item);
                        if (pid.equals(str)) {
                            return true;
                        }
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    return false;
                })
                .forEach(item -> {
                    try {
                        T vo = (T) item.getClass().getDeclaredConstructor().newInstance();
                        BeanUtils.copyProperties(item, vo);
                        Field fieldId = item.getClass().getDeclaredField("id");
                        fieldId.setAccessible(true);
                        String str = fieldId.get(item).toString();
                        List<T> children = makeTreeForAny(menuList, str);
                        Field fieldChildren = vo.getClass().getDeclaredField("children");
                        fieldChildren.setAccessible(true);
                        fieldChildren.set(vo, children);
                        list.add(vo);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
        return list;
    }

}
